package com.sen.common.security;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import com.sen.common.utils.web.ServletUtils;

/**
 * 把文本转变成图片的生成器.
 *
 * <pre>
 * 若在web.xml里配置的servlet名为: /security/convertion.
 * 调用参数有: <ol>
 * <li>text : 指定显示信息
 * <li>width: 生成图片的宽度, 默认为120px
 * <li>height: 生成图片的高度, 默认为20px
 * <li>bgcolor: 背景颜色, 默认为255,255,255
 * <li>color: 字体颜色, 默认为0,0,0
 * <li>font: 字体, 默认为Arial
 * <li>fontsize: 字体大小, 默认为13px
 * <li>boldable: 是否加粗, 默认为false
 * </ol>
 * </pre>
 * 
 * @author sen
 */
public class TextImageConvertionServlet extends HttpServlet {

	private static final long serialVersionUID = -7966404083535796672L;

	/**
	 * 字体颜色.
	 */
	private static final String BACKGROUND_COLOR_PARAM = "bgcolor";
	/**
	 * 字体颜色.
	 */
	private static final String COLOR_PARAM = "color";
	/**
	 * 字体.
	 */
	private static final String TEXT_FONT_PARAM = "font";
	/**
	 * 字体大小.
	 */
	private static final String TEXT_FONT_SIZE_PARAM = "fontSize";
	private static final String TEXT_PARAM = "text";
	private static final String IMAGE_WIDTH_PARAM = "width";
	private static final String IMAGE_HEIGHT_PARAM = "height";
	private static final String BOLDABLE_PARAM = "boldable";

	private static final String DEFAULT_BACKGROUND_COLOR = "255,255,255";
	private static final String DEFAULT_COLOR = "0,0,0";
	private static final String DEFAULT_TEXT_FONT = "Arial";
	private static final int DEFAULT_TEXT_FONT_SIZE = 13;
	private static final int DEFAULT_IMAGE_WIDTH = 120;
	private static final int DEFAULT_IMAGE_HEIGHT = 20;
	private static final boolean DEFAULT_BOLDABLE = false;

	private static String bgcolor = DEFAULT_BACKGROUND_COLOR;
	private static String color = DEFAULT_COLOR;
	private static String font = DEFAULT_TEXT_FONT;
	private static int fontSize = DEFAULT_TEXT_FONT_SIZE;
	

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		initParameters(config);
	}
	
	/**
	 * 初始化web.xml中定义的servlet init-param.
	 */
	private void initParameters(final ServletConfig config) {
		if (StringUtils.isNotBlank(config.getInitParameter(BACKGROUND_COLOR_PARAM))) {
			bgcolor = config.getInitParameter(BACKGROUND_COLOR_PARAM);
		}
		if (StringUtils.isNotBlank(config.getInitParameter(COLOR_PARAM))) {
			color = config.getInitParameter(COLOR_PARAM);
		}
		if (StringUtils.isNotBlank(config.getInitParameter(TEXT_FONT_PARAM))) {
			font = config.getInitParameter(TEXT_FONT_PARAM);
		}
		if (StringUtils.isNotBlank(config.getInitParameter(TEXT_FONT_SIZE_PARAM))) {
			fontSize = Integer.valueOf(config.getInitParameter(TEXT_FONT_SIZE_PARAM));
		}
	}
	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String text = request.getParameter(TEXT_PARAM);
		if (StringUtils.isBlank(text)) {
			return;
		}
		ServletUtils.setDisableCacheHeader(response);
		response.setContentType("image/jpeg");

		int imageWidth = DEFAULT_IMAGE_WIDTH;
		int imageHeight = DEFAULT_IMAGE_HEIGHT;
		if (StringUtils.isNotBlank(request.getParameter(IMAGE_WIDTH_PARAM))) {
			imageWidth = Integer.valueOf(request.getParameter(IMAGE_WIDTH_PARAM));
		}
		if (StringUtils.isNotBlank(request.getParameter(IMAGE_HEIGHT_PARAM))) {
			imageHeight = Integer.valueOf(request.getParameter(IMAGE_HEIGHT_PARAM));
		}
		BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
		
		addTextImage(request, imageWidth, imageHeight, image);
		// 设置背景色
		image = addBackground(request, imageWidth, imageHeight, image);
		
		ImageIO.write(image, "jpg", response.getOutputStream());
	}
	
	private void addTextImage(HttpServletRequest request, int imageWidth, int imageHeight, BufferedImage image) {
		String text = request.getParameter(TEXT_PARAM);
		String textColor = color;
		if (StringUtils.isNotBlank(request.getParameter(COLOR_PARAM))) {
			textColor = request.getParameter(COLOR_PARAM);
		}
		String textFont = font;
		if (StringUtils.isNotBlank(request.getParameter(TEXT_FONT_PARAM))) {
			textFont = request.getParameter(TEXT_FONT_PARAM);
		}
		int textFontSize = fontSize;
		if (StringUtils.isNotBlank(request.getParameter(TEXT_FONT_SIZE_PARAM))) {
			textFontSize = Integer.valueOf(request.getParameter(TEXT_FONT_SIZE_PARAM));
		}
		boolean boldable = DEFAULT_BOLDABLE;
		if (StringUtils.isNotBlank(request.getParameter(BOLDABLE_PARAM))) {
			boldable = Boolean.valueOf(request.getParameter(BOLDABLE_PARAM));
		}
		Graphics2D graphics = image.createGraphics();

		graphics.setColor(createColor(textColor));
		graphics.setFont(new Font(textFont, boldable ? Font.BOLD : Font.PLAIN, textFontSize));

		int x = 0, y = (imageHeight - textFontSize) / 5 + textFontSize;
		graphics.drawString(text, x, y);
	}
	
	private BufferedImage addBackground(HttpServletRequest request, int imageWidth, int imageHeight, BufferedImage image) {
		String imageBgColor = bgcolor;
		if (StringUtils.isNotBlank(request.getParameter(BACKGROUND_COLOR_PARAM))) {
			imageHeight = Integer.valueOf(request.getParameter(BACKGROUND_COLOR_PARAM));
		}
		// create an opaque image
		BufferedImage imageWithBackground = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);

		Graphics2D graphics = (Graphics2D) imageWithBackground.getGraphics();

		graphics.setColor(createColor(imageBgColor));
		graphics.fill(new Rectangle2D.Double(0, 0, imageWidth, imageHeight));

		// draw the transparent image over the background
		graphics.drawImage(image, 0, 0, null);

		return imageWithBackground;
	}
	
	private Color createColor(String color) {
		String[] colors = StringUtils.split(color, ',');
		int red = Integer.valueOf(colors[0]);
		int green = Integer.valueOf(colors[1]);
		int blue = Integer.valueOf(colors[2]);
		return new Color(red, green, blue);
	}
}
